package com.siqi.hr.system.common.service;

import com.siqi.hr.common.Constants;
import com.siqi.hr.common.redis.RedisAPI;
import com.siqi.hr.common.utils.Const;
import com.siqi.hr.common.utils.FileUtils;
import com.siqi.hr.common.utils.StringUtil;
import com.siqi.hr.common.utils.TableConstant;
import com.siqi.hr.system.common.authority.DataScope;
import com.siqi.hr.system.common.chan.*;
import com.siqi.hr.system.common.dao.intf.CommonOperationDao;
import com.siqi.hr.system.common.enums.FieldEditPageEnum;
import com.siqi.hr.system.common.enums.FieldPosition;
import com.siqi.hr.system.common.model.filter.QueryDataEntity;
import com.siqi.hr.system.common.sql.Condition;
import com.siqi.hr.system.common.sql.SField;
import com.siqi.hr.system.common.sql.STable;
import com.siqi.hr.system.common.utils.TableDatas;
import com.siqi.hr.system.custom.dao.intf.EntityRecordDao;
import com.siqi.hr.system.custom.dao.intf.FieldEmployeeDao;
import com.siqi.hr.system.custom.dao.intf.SelectBoxDao;
import com.siqi.hr.system.custom.entity.EntityRecord;
import com.siqi.hr.system.custom.entity.FieldRecord;
import com.siqi.hr.system.organization.dao.intf.RoleDao;
import com.siqi.hr.system.organization.entity.Dept;
import com.siqi.hr.system.organization.entity.Employee;
import com.siqi.hr.system.organization.entity.RoleEntityScope;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;

import java.util.*;

/**
 * 处理公共操作方法通用service层
 * @version 1.0.0, Sep 25, 2016
 * @author xiaoxiumei
 * @since JDK1.6.0_12, Spring3.0.2
 */
@Service("commonOperationService")
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public class CommonOperationService{

	@Autowired
	private FieldEmployeeDao fieldEmployeeDao;
	@Autowired
	private CommonOperationDao commonOperationDao;
	@Autowired
	private EntityRecordDao entityRecordDao;
	@Autowired
	private RoleDao roleDao;
	@Autowired
	private SelectBoxDao selectBoxDao;

	/**
	 * 获取实体所有字段数据(xiaogq)
	 * entityId                 实体id
	 * @param position       实体列表布局或过滤条件布局标识(List:列表布局，Falter：过滤条件布局)
	 * @return
	 */
	public List<FieldRecord> queryAllEntityLayoutField(Integer entityId,FieldPosition position){
		List<FieldRecord> allField = new ArrayList<FieldRecord>();
		try {
			allField = fieldEmployeeDao.queryAllEntityLayoutField(entityId, position);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return allField;
	}

	/**
	 * 获取管理员设置的列表布局，过滤条件字段(xiaogq)
	 * @param entityId        实体id
	 * @param position        实体列表布局或过滤条件布局标识(List:列表布局，Falter：过滤条件布局)
	 * @return
	 */
	public List<FieldRecord> querySysSetEntityLayoutField(Integer entityId,FieldPosition position){
		List<FieldRecord> fields = new ArrayList<FieldRecord>();
		try {
			fields = fieldEmployeeDao.querySysSetEntityLayoutField(entityId, position);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return fields;
	}

	public List<FieldRecord> queryEmpSetEntityLayoutField(String employeeId,Integer entityId, FieldPosition position){
		List<FieldRecord> fieldList = new ArrayList<FieldRecord>();
		try {
			fieldList = fieldEmployeeDao.queryEmpSetEntityLayoutField(employeeId, entityId, position);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return fieldList;
	}

	/**
	 * 保存用户布局、过滤条件设置(xiaoxm)
	 * @param employeeId       当前登录系统用户Id
	 * @param entityId         实体Id
	 * @param position         列表布局或过滤条件字段标识（List:列表布局，Filter:过滤条件布局）
	 * @param fieldList        设置的字段信息
	 * @param isDefault        是系统布局还是自定义布局标识(true:系统布局，false：自定义布局)
     */
	public void saveFieldEmployeeLayout(String employeeId, Integer entityId,FieldPosition position, List<FieldRecord> fieldList, boolean isDefault) throws Exception{
		int lens = fieldEmployeeDao.saveFieldEmployeeLayout(employeeId, entityId,position, fieldList, isDefault);
		if(lens > 0){//设置实体布局、过滤条件缓存xiaogq
			if(isDefault){
				RedisAPI.setKeyObject(entityId+"_"+position.name(),fieldList,Constants.DEFAULTDB_INDEX);
			}else{
				RedisAPI.setKeyObject(entityId+"_"+employeeId+"_"+position.name(),fieldList,Constants.DEFAULTDB_INDEX);
			}
		}
	}

	/**
	 *  通用的客户化对象列表查询方法(xiaogq)
	 * @param queryDataEntity         封装拼sql语句对象
	 * @return
	 */
	public Map<String, Object> queryCustomObjectAll(QueryDataEntity queryDataEntity) throws Exception{
		Map<String, Object> resultMap = new HashMap<String,Object>();
		//获取实体id
		int tableCode = queryDataEntity.getTableCode();
		EntityRecord entityRecord = entityRecordDao.queryEntityRecordById(tableCode);
		// sql对象
		TSQLSelectStat stat = new TSQLSelectStat();
		stat.setEmployee(queryDataEntity.getEmployee());
		Dept dept = queryDataEntity.getDept();
		//如果是员工档案实体，并且部门等级不为空
		if(tableCode == TableConstant.EMPLOYEE_TCODE && StringUtils.isNotBlank(queryDataEntity.getDeptScope())){
			dept.setDeptRank(queryDataEntity.getDeptScope());
		}
		stat.setDept(dept);
		// 表
		final STable sTable = new STable( queryDataEntity.getTableName() );
		TableChan tableChan = new TableChan(sTable);
		// 字段
		List<SField> sf = new ArrayList<SField>();
		stat.setTableChan(tableChan);
		stat.setTablecode(tableCode);
		//是否存在下拉多选字段
		List<String> muitlBoxFields =  new ArrayList<String>();
		for( String field : queryDataEntity.getFields() ){
			field = field.trim();
			if(field.indexOf("_mutibox") != -1){
				muitlBoxFields.add(field);
			}
			sf.add(new SField( field, sTable ));
		}
		// 设置字段
		if( sf.size() == 0 ) return null;
		stat.setFieldChan(new FieldChan(sf));
		// 指定查询的数据ID
		String searchIds = StringUtil.getString(queryDataEntity.getSearchIds());
		ConditionChan cc = new ConditionChan();
		//设置没有停用的数据条件
		//cc.add(new Condition(new SField("flag_bit",new STable(STable.TABLE_HEAD+tableCode)), Condition.ConditionType.eq ,queryDataEntity.isFlag()+""));
		if( StringUtils.isNotEmpty(searchIds) ){
			cc.add(new Condition(new SField("id",new STable(STable.TABLE_HEAD+tableCode)), Condition.ConditionType.notin , searchIds));
		}
		// 添加是否有效数据验证条件
		Condition validCondition = listValidDataCondition(queryDataEntity,entityRecord);
		if(null != validCondition){
			cc.add(validCondition);
		}

		// 数据权限（肖功钦）
		RoleEntityScope scope = new RoleEntityScope(DataScope.NONE.name());
		//如果实体不是受权限控制的实体
		if( !entityRecord.getPermission()){
			scope = new RoleEntityScope(DataScope.ALL.name());
		}else{//如果实体是受权限控制的实体(肖功钦)
			scope = roleDao.queryRoleDataScope(queryDataEntity.getEmployee().getRole().getId(), entityRecord);
		}
		//如果是员工档案实体，并且部门等级不为空
		if(tableCode == TableConstant.EMPLOYEE_TCODE && StringUtils.isNotBlank(queryDataEntity.getDeptScope())){
			scope = new RoleEntityScope(DataScope.SIBLING_AND_SUBORDINATE.name());
		}
		stat.setScope(scope);

		// 其他过滤条件
		Set<Condition> conditios = queryDataEntity.getMutilSearch();
		//普通查询处理
		for(Condition condition : conditios){
			cc.add(condition);	//加入条件族
		}
		stat.setConditionChan(cc);
		stat.setBootstrapQuery(queryDataEntity.isBootstrapQuery());
		stat.setSearchVal(queryDataEntity.getSearch());
		// 排序
		if(StringUtils.isNotBlank(queryDataEntity.getSort())){
			//如果排序字段是引用属性，需要特殊处理
			String tableName = queryDataEntity.getTableName();
			String sortName = queryDataEntity.getSort();
			stat.setOrderby(tableName+"."+sortName + " " + (StringUtils.isEmpty(queryDataEntity.getOrder()) ? " asc " : queryDataEntity.getOrder()));
		}else{
			stat.setOrderby(queryDataEntity.getTableName()+".id " + (StringUtils.isEmpty(queryDataEntity.getOrder()) ? " asc " : queryDataEntity.getOrder()));
		}
		// 分页
		if( queryDataEntity.isUsepager() && queryDataEntity.getLimit() != 0){
			String limit = (queryDataEntity.getOffset()+ "," + queryDataEntity.getLimit());
			stat.setLimit(limit);
		}
		// 查询数量的SQL对象
		TSQLCountSelectStat countStat = new TSQLCountSelectStat(stat);
		Long count = commonOperationDao.queryForCount(countStat);

		// 查询列表的	SQL对象
		TSqlListSelectStat listSql = new TSqlListSelectStat(stat);
		// 结果
		TableDatas datas = commonOperationDao.queryForList(listSql);
		List<Map<String, Object>> rows = datas.extractValus(queryDataEntity);
		resultMap.put(Const.ROWS, rows);
		resultMap.put(Const.TOTAL, count);
		return resultMap;
	}

	/**
	 * 根据实体是否是回收站实体给列表添加“查询有效数据”条件
	 *@author     xiagq 2016 08 24
	 *@param      queryDataEntity       搜索条件对象
	 *@return     entityRecord             实体对象信息
	 */
	public Condition listValidDataCondition(QueryDataEntity queryDataEntity,EntityRecord entityRecord){
		Integer entityId = queryDataEntity.getTableCode();
		Set<Condition> conditios = queryDataEntity.getMutilSearch();
		//判断过滤条件里是否包含是否有效数据的验证
		Condition validCond = null;
		Boolean contain = false;
		for(Condition con : conditios){
			if (con.getField().getName().equals("valid_data_bit")) {
				contain = true;
				validCond = con;
				break;
			}
		}
		//如果没有是否有效数据的验证，则判断是否使用回收站实体，是使用回收站实体默认添加是否有效数据的验证
		if(!contain){
			if(entityRecord.getUseRecyclebin()){
				return new Condition(new SField("valid_data_bit", new STable(queryDataEntity.getTableName())), Condition.ConditionType.eq,queryDataEntity.isValidFlag()+"");
			}
		}
		return validCond;
	}

	/**
	 * 获取角色权限编辑页、详情页显示的字段
	 * @author               xiaogq
	 * @param entityId      实体id
	 * @param roleId        角色id
	 * @param pageEnum      是查看页字段布局还是编辑页
	 * @throws Exception
	 */
	public List<FieldRecord> getEditOrViewPageFields(int entityId, String roleId,FieldEditPageEnum pageEnum) throws Exception{
		//RedisAPI.delKey(entityId+"_"+roleId+"_"+pageEnum.name(),Constants.DEFAULTDB_INDEX);
		//先从缓存中取编辑页、查看页布局字段
		List<FieldRecord> editFields = (List<FieldRecord>) RedisAPI.getKeyObject(entityId+"_"+roleId+"_"+pageEnum.name(),Constants.DEFAULTDB_INDEX);
		if(editFields == null || editFields.size() ==0){
			editFields = commonOperationDao.getEditOrViewPageFields(entityId,roleId,pageEnum);
			RedisAPI.setKeyObject(entityId+"_"+roleId+"_"+pageEnum.name(),editFields,Constants.DEFAULTDB_INDEX);
		}
		return editFields;
	}

	/**
	 * 查询添加、编辑页显示字段对象信息
	 * @author              xiaogq
	 * @param entityId     实体id
	 * @param fields       添加，编辑页字段信息
	 * @return
     * @throws Exception
     */
	public List<Map<String, Object>> getEditPageFields(int entityId, List<FieldRecord> fields) throws Exception{
		List<Map<String, Object>> fieldRecords = new ArrayList<Map<String, Object>>();
		for(FieldRecord record : fields){
			Map<String, Object> map = new HashedMap();
			List<Map<String, Object>> datas = new ArrayList<Map<String, Object>>();
			if(record.getName().endsWith("_singlebox") || record.getName().endsWith("_radio") || record.getName().endsWith("_mutibox")){
				datas = fieldEmployeeDao.queryEntityFieldSelectBox(entityId, record);
			}
			map.put("fieldRecord", record);
			map.put("datas", datas);
			fieldRecords.add(map);
		}
		return fieldRecords;
	}

	/**
	 * 查询添加、编辑页显示字段对象信息
	 * @author              xiaogq
	 * @param dataId       数据记录id
	 * @param entityId     实体id
	 * @param roleId        角色id
	 * @param pageEnum      查询添加/编辑、查看页字段标识
	 * @return
	 * @throws Exception
	 */
	public Map<String, Object> getViewPageFields(String dataId,int entityId, String roleId,FieldEditPageEnum pageEnum) throws Exception{
		Map<String, Object> resultMap = new HashMap<String,Object>();
		List<FieldRecord> records = this.getEditOrViewPageFields(entityId, roleId,pageEnum);
		resultMap.put("fieldRecord",records);
		// sql对象
		TSQLSelectStat stat = new TSQLSelectStat();
		// 表
		final STable sTable = new STable(STable.TABLE_HEAD + entityId);
		TableChan tableChan = new TableChan(sTable);
		stat.setTableChan(tableChan);
		stat.setTablecode(entityId);
		List<SField> sf = new ArrayList<SField>();
		ConditionChan cc = new ConditionChan();
		for(FieldRecord record : records){
			sf.add(new SField( record.getName(), sTable ));
		}
		stat.setFieldChan(new FieldChan(sf));
		cc.add(new Condition(new SField("id",sTable), Condition.ConditionType.eq,dataId));
		stat.setConditionChan(cc);
		// 查询列表的	SQL对象
		TSQLViewSelectStat viewSql = new TSQLViewSelectStat(stat);
		// 结果
		Map<String,Object> datas = commonOperationDao.queryViewDatasById(viewSql);
		//处理特殊字段值
		Map<String, Object> datasMap = selectBoxDao.extractViewDataValus(datas,dataId);
		//System.out.println("datasMap==="+datasMap);
		resultMap.put("datas",datasMap);
		return resultMap;
	}

	/**
	 * 添加自定义实体保存方法
	 * @param dataMap            前台页面form表单提交的值
	 * @param entityRecord      实体对象
	 * @param emp                 当前登陆系统用户信息对象
	 * @param multipartRequest  文件上传对象
	 * @throws Exception
	 */
	public String addTData(Map<String,Object> dataMap, EntityRecord entityRecord, Employee emp, DefaultMultipartHttpServletRequest multipartRequest){
		String id = "";
		try {
			//处理文件上传
			if(multipartRequest != null){
				for (Map.Entry<String, MultipartFile> entry : multipartRequest.getFileMap().entrySet()) {
					MultipartFile file = entry.getValue();
					byte[] contents = file.getBytes();
					if (contents == null || contents.length == 0) {
						continue;
					}
					String filePath = FileUtils.uploadFiles(file);
					dataMap.put(file.getName(),filePath);
				}
			}
			id = commonOperationDao.addTData(dataMap, entityRecord, emp);
		}catch (Exception e){
			e.printStackTrace();
		}
		return id;
	}

	/**
	 * 根据id查询数据、含外键表对象id、英文名、中文名
	 * @author        xiaogq
	 * @param         entityId     实体id
	 * @param         id            记录id
	 * @param         fields       要查询的字段信息
	 * @author ChenL
	 */
	public Map<String ,Object> queryTDataInfoById(int entityId,String id,List<FieldRecord> fields) throws Exception{
		// sql对象
		TSQLSelectStat stat = new TSQLSelectStat();
		// 表
		final STable sTable = new STable(STable.TABLE_HEAD + entityId);
		TableChan tableChan = new TableChan(sTable);
		stat.setTableChan(tableChan);
		stat.setTablecode(entityId);
		List<SField> sf = new ArrayList<SField>();
		ConditionChan cc = new ConditionChan();
		for(FieldRecord record : fields){
			sf.add(new SField( record.getName(), sTable ));
		}
		stat.setFieldChan(new FieldChan(sf));
		cc.add(new Condition(new SField("id",sTable), Condition.ConditionType.eq,id));
		stat.setConditionChan(cc);
		// 查询列表的	SQL对象
		TSQLViewSelectStat viewSql = new TSQLViewSelectStat(stat);
		// 结果
		Map<String,Object> datas = commonOperationDao.queryViewDatasById(viewSql);
		//处理特殊字段值
		Map<String, Object> resultMap = selectBoxDao.extractViewDataValus(datas,id);
		//System.out.println("datasMap==="+datasMap);
		return resultMap;
	}

	/**
	 * 修改自定义实体保存方法
	 * @param dataMap
	 * @param entityRecord
	 * @param emp
	 * @param id
	 * @param multipartRequest
	 * @return
	 * @throws Exception
	 */
	public int updateTData(final Map<String,Object> dataMap, EntityRecord entityRecord, Employee emp, String id, DefaultMultipartHttpServletRequest multipartRequest){
		int index = 0;
		try {
			//处理文件上传
			if(multipartRequest != null){
				for (Map.Entry<String, MultipartFile> entry : multipartRequest.getFileMap().entrySet()) {
					MultipartFile file = entry.getValue();
					byte[] contents = file.getBytes();
					if (contents == null || contents.length == 0) {
						continue;
					}
					String filePath = FileUtils.uploadFiles(file);
					dataMap.put(file.getName(),filePath);
				}
			}
			index = commonOperationDao.updateTData(dataMap, entityRecord, emp, id);
		}catch (Exception e){
			e.printStackTrace();
		}
		return index;
	}

	/**
	 * 通用数据删除
	 * @author   xiaogq
	 * @param entityRecord   实体对象信息
	 * @param id
	 * @throws Exception
	 */
	public JSONObject deleteTData(EntityRecord entityRecord, String id) throws Exception{
		JSONObject obj = new JSONObject();
		STable table = new STable(STable.TABLE_HEAD + entityRecord.getTableCode());
		//如果是使用回收站实体
		if(entityRecord.getUseRecyclebin()){
			commonOperationDao.updateValidData(table,id);
		}else{//如果没有回收站实体，则直接删除数据
			//删除数据时该记录是否被其他表引用
			JSONArray quoteArray = new JSONArray();
			String quoteList = RedisAPI.get(table.getName(), Constants.DEFAULTDB_INDEX);
			if(StringUtils.isNotBlank(quoteList)){
				quoteArray = JSONArray.fromObject(quoteList);
			}else{
				quoteArray = commonOperationDao.getAllQuoteTableInfo(table.getName());
			}
			List<Map<String,Object>> resultList = commonOperationDao.isQuoteByOtherTable(quoteArray,id);
			if(resultList.size() > 0){
				obj.put("flag","改记录以及被其他实体引用,不能删除!");
			}else{
				obj.put("flag","true");
				commonOperationDao.deleteTData(table, id);
			}
		}
		return obj;
	}

    /**
	 * 添加实体相关关系通用方法
	 * @author     xiaogq
	 * @param      tableName      关系表名
	 * @param      hostId         主实体记录id
	 * @param      relatedIds     相关实体记录id
	 * @return
     */
	public JSONObject addEntityRelation(String tableName,String hostId,String relatedIds){
		JSONObject obj = new JSONObject();
		int counts = commonOperationDao.addEntityRelation(tableName,hostId,relatedIds);
		obj.put("flag",counts > 0);
		return obj;
	}

	/**
	 * 导入得到实体的全部字段Service方法
	 * @author xiaogq
	 * @param entityId   实体id
	 * @return
	 */
	public Map<String, Object> getAllFieldsOfEntityExceptQuote(Integer entityId) {
		Map<String, Object> fieldMap = commonOperationDao.getAllFieldsOfEntityExceptQuote(entityId);
		return fieldMap;
	}

	/**
	 * 判断数据是否停用(1:停用，0：启用)
	 * @author             xiaogq
	 * @param tableName    实体表名
	 * @param id           记录id
	 * @return
	 */
	public boolean dataIsDisable(String tableName,String id){
		STable table = new STable(tableName);
		return commonOperationDao.dataIsDisable(table, id);
	}

	/**
	 * 通用数据停用
	 * @param tableName
	 * @param id
	 * @throws Exception
	 */
	public void disableTDate(String tableName, String id) throws Exception{
		STable table = new STable(tableName);
		commonOperationDao.disableTDate(table, id);
	}

	/**
	 * 通用数据启用
	 * @param tableName
	 * @param id
	 * @throws Exception
	 */
	public void enableTDate(String tableName, String id) throws Exception{
		STable table = new STable(tableName);
		commonOperationDao.enableTDate(table, id);
	}

}

